package top.goldenyear.porpoise.framework.web.core.util;

import top.goldenyear.porpoise.framework.common.constant.PorpoiseHeader;
import top.goldenyear.porpoise.framework.web.config.WebProps;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import cn.hutool.v7.core.math.NumberUtil;
import cn.hutool.v7.core.text.StrUtil;
import org.noear.snack.ONode;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.DownloadedFile;
import org.noear.solon.core.util.MimeType;
import org.noear.solon.core.util.MultiMap;

/**
 * 专属于 web 包的工具类
 *
 * @author Airhead
 */
public class WebUtils {

  public static final String HEADER_TENANT_ID = "tenant-id";

  private static final String REQUEST_ATTRIBUTE_COMMON_RESULT = "common_result";
  private static WebProps webProps;

  public static void setWebProperties(WebProps webProps) {
    WebUtils.webProps = webProps;
  }

  /**
   * 获得租户编号，从 header 中 考虑到其它 framework 组件也会使用到租户编号，所以不得不放在 WebFrameworkUtils 统一提供
   *
   * @param context 请求
   * @return 租户编号
   */
  public static Long getTenantId(Context context) {
    String tenantId = context.header(HEADER_TENANT_ID);
    return NumberUtil.isNumber(tenantId) ? Long.valueOf(tenantId) : null;
  }

  public static Object getRequest() {
    return Context.current().request();
  }

  /**
   * 返回 JSON 字符串
   *
   * @param context 响应
   * @param object 对象，会序列化成 JSON 字符串
   */
  public static void renderJson(Context context, Object object) {
    String content = ONode.stringify(object);
    context.outputAsJson(content);
  }

  /**
   * 返回 图片
   *
   * @param context 响应
   * @param data 对象，会序列化成 JSON 字符串
   */
  public static void renderImage(Context context, byte[] data) {
    context.headerSet("Content-Type", MimeType.IMAGE_JPEG_VALUE);
    try (OutputStream outputStream = context.outputStream()) {
      outputStream.write(data);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 返回附件
   *
   * @param context 响应
   * @param filename 文件名
   * @param content 附件内容
   */
  public static void renderFile(Context context, String filename, byte[] content)
      throws IOException {
    InputStream stream = new ByteArrayInputStream(content);
    DownloadedFile file =
        new DownloadedFile(
            MimeType.APPLICATION_OCTET_STREAM_VALUE,
            stream,
            URLEncoder.encode(filename, StandardCharsets.UTF_8));
    context.outputAsFile(file);
  }

  /**
   * 返回附件
   *
   * @param context 响应
   * @param filename 文件名
   * @param inputStream 附件内容
   */
  public static void renderFile(Context context, String filename, InputStream inputStream)
      throws IOException {
    DownloadedFile file =
        new DownloadedFile(
            MimeType.APPLICATION_OCTET_STREAM_VALUE,
            inputStream,
            URLEncoder.encode(filename, StandardCharsets.UTF_8));
    context.outputAsFile(file);
  }

  /**
   * 返回附件
   *
   * @param context 响应
   * @param filename 文件名
   * @param inputStream 附件内容
   */
  public static void renderFile(
      Context context, String filename, String contentType, InputStream inputStream)
      throws IOException {
    DownloadedFile file =
        new DownloadedFile(
            contentType, inputStream, URLEncoder.encode(filename, StandardCharsets.UTF_8));
    context.outputAsFile(file);
  }

  /**
   * 返回附件
   *
   * @param context 响应
   */
  public static void renderFile(Context context, File file) throws IOException {
    context.outputAsFile(new DownloadedFile(file));
  }

  /**
   * @param context 请求
   * @return ua
   */
  public static String getUserAgent(Context context) {
    return context.userAgent();
  }

  public static String getUserAgent() {
    return getUserAgent(Context.current());
  }

  public static String getClientIP() {
    return getClientIP(Context.current());
  }

  public static boolean isJsonRequest(Context context) {
    return StrUtil.startWithIgnoreCase(context.contentType(), MimeType.APPLICATION_JSON_VALUE);
  }

  public static String getBody(Context context) {
    try {
      return context.body();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static byte[] getBodyBytes(Context context) {
    try {
      return context.bodyAsBytes();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public static String getClientIP(Context context) {
    return context.realIp();
  }

  public static MultiMap<String> getParamMap(Context context) {
    return context.paramMap();
  }

  public static String getCaptchaKey() {
    Context context = Context.current();
    String captchaKey = context.cookie("_porpoise_captcha");
    if (StrUtil.isBlank(captchaKey)) {
      captchaKey = context.header(PorpoiseHeader.PORPOISE_CAPTCHA_KEY);
    }

    return captchaKey;
  }
}
